{
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "Tce3stUlHN0L"
      },
      "source": [
        "##### Copyright 2019 The TensorFlow Authors."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "cellView": "form",
        "id": "tuOe1ymfHZPu"
      },
      "outputs": [],
      "source": [
        "#@title Licensed under the Apache License, Version 2.0 (the \"License\");\n",
        "# you may not use this file except in compliance with the License.\n",
        "# You may obtain a copy of the License at\n",
        "#\n",
        "# https://www.apache.org/licenses/LICENSE-2.0\n",
        "#\n",
        "# Unless required by applicable law or agreed to in writing, software\n",
        "# distributed under the License is distributed on an \"AS IS\" BASIS,\n",
        "# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n",
        "# See the License for the specific language governing permissions and\n",
        "# limitations under the License."
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "qFdPvlXBOdUN"
      },
      "source": [
        "# Оценщики"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "MfBg1C5NB3X0"
      },
      "source": [
        "<table class=\"tfo-notebook-buttons\" align=\"left\">\n",
        "  <td>\n",
        "    <a target=\"_blank\" href=\"https://www.tensorflow.org/guide/estimator\"><img src=\"https://www.tensorflow.org/images/tf_logo_32px.png\" />Смотрите на TensorFlow.org</a>\n",
        "  </td>\n",
        "  <td>\n",
        "    <a target=\"_blank\" href=\"https://colab.research.google.com/github/tensorflow/docs-l10n/blob/master/site/ru/guide/estimator.ipynb\"><img src=\"https://www.tensorflow.org/images/colab_logo_32px.png\" />Запустите в Google Colab</a>\n",
        "  </td>\n",
        "  <td>\n",
        "    <a target=\"_blank\" href=\"https://github.com/tensorflow/docs-l10n/blob/master/site/ru/guide/estimator.ipynb\"><img src=\"https://www.tensorflow.org/images/GitHub-Mark-32px.png\" />Изучайте код на GitHub</a>\n",
        "  </td>\n",
        "  <td>\n",
        "    <a href=\"https://storage.googleapis.com/tensorflow_docs/docs-l10n/site/ru/guide/estimator.ipynb\"><img src=\"https://www.tensorflow.org/images/download_logo_32px.png\" />Скачайте ноутбук</a>\n",
        "  </td>\n",
        "</table>"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "fj66ZXAzrJC2"
      },
      "source": [
        "Note: Данный раздел переведён с помощью русскоязычного сообщества Tensorflow на общественных началах. Поскольку перевод не является официальным, мы не гарантируем, что он на 100% точен и соответствует [официальной документации на английском языке](https://www.tensorflow.org/?hl=en). Если у вас есть предложения по исправлению перевода, мы будем очень рады увидеть pull request в репозиторий [tensorflow/docs-l10n](https://github.com/tensorflow/docs-l10n) на GitHub. Если вы хотите помочь сделать документацию по Tensorflow лучше (выполнить перевод или проверить перевод, подготовленный кем-то другим), напишите нам на [docs-ru@tensorflow.org list](https://groups.google.com/a/tensorflow.org/forum/#!forum/docs-ru)."
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "oEinLJt2Uowq"
      },
      "source": [
        "Этот документ знакомит с `tf.estimator` — высокоуровневым TensorFlow\n",
        "API. Оценщики включают следующие действия:\n",
        "\n",
        "* обучение\n",
        "* оценка\n",
        "* предсказание\n",
        "* экспорт для serving\n",
        "\n",
        "Вы можете использовать созданные нами оценщики или\n",
        "собственные кастомные оценщики.  Все оценщики - как созданные нами, так и пользовательские - являются\n",
        "классами, основанными на классе `tf.estimator.Estimator`.\n",
        "\n",
        "Быстрый пример можно посмотреть в [Учебниках по оценщикам](../../tutorials/estimator/linear.ipynb). Обзор структуры API приведен в [статье](https://arxiv.org/abs/1708.02637)."
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "Wg5zbBliQvNL"
      },
      "source": [
        "## Преимущества\n",
        "\n",
        "Аналогично `tf.keras.Model`, `estimator` это абстракция на уровне модели. `tf.estimator` предоставляет некоторые возможности, которые все еще находятся в стадии разработки для `tf.keras`. Это:\n",
        "\n",
        "  * Обучение на сервере параметров\n",
        "  * Полная [TFX](http://tensorflow.org/tfx) интеграция."
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "yQ8fQYt_VD5E"
      },
      "source": [
        "## Возможности оценщиков\n",
        "Оценщики предоставляют следующие преимущества:\n",
        "\n",
        "* Вы можете запускать модели на основе оценщиков на локальном компьютере или в распределенной многосерверной среде без изменения вашей модели. Кроме того, вы можете запускать модели на основе оценщиков на CPU, GPU, или TPU без изменения исходного кода вашей модели.\n",
        "* Оценщики обеспечивают безопасный распределенный цикл обучения, который контролирует каким образом и когда:\n",
        "    * загружаются данные\n",
        "    * обрабатываются исключения\n",
        "    * создаются файлы чекпоинтов и восстанавливаются после сбоев\n",
        "    * сохраняются сводные данные для TensorBoard\n",
        "\n",
        "При написании приложения с оценщиками, вы должны отделить конвейер входных данных\n",
        "от модели. Это разделение упрощает эксперименты с различными наборами данных."
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "sXNBeY-oVxGQ"
      },
      "source": [
        "## Готовые оценщики\n",
        "\n",
        "Предварительно созданные оценщики позволяют вам работать на гораздо более высоком концептуальном уровне, чем базовые API TensorFlow. Вам больше не нужно беспокоиться о создании вычислительного графа или сессий, поскольку оценщики делают всю \"грязную работу\" за вас. Кроме того, оценщики, позволяют вам экспериментировать с различными архитектурами моделей, внося только минимальные изменения в код. `tf.estimator.DNNClassifier`, например, представляет собой заранее подготовленный класс Estimator, который обучает модели классификации на основе полносвязных нейронных сетей прямого распространения.\n",
        "\n",
        "### Структура программы на готовом оценщике\n",
        "\n",
        "Создание программы TensorFlow на готовом оценщике обычно состоит из четырех этапов:\n",
        "\n",
        "#### 1. Напишите одну или несколько функций импорта данных.\n",
        "\n",
        "Например, вы можете создать одну функцию для импорта тренировочных данных и другую функцию для импорта тестовых данных. Каждая функция импорта данных должна возвращать два объекта:\n",
        "\n",
        "* словарь, в котором ключами являются имена признаков, а значениями - тензоры (Tensor или SparseTensor), содержащие соответствующие признаку данные\n",
        "* Tensor, содержащий одну или более меток\n",
        "\n",
        "Например, следующий код иллюстрирует базовый каркас для входной функции:\n",
        "\n",
        "```\n",
        "def input_fn(dataset):\n",
        "    ...  # манипулирет датасетом, извлекает словарь со свойствами и метку\n",
        "    return feature_dict, label\n",
        "```\n",
        "\n",
        "See [data guide](../../guide/data.md) for details.\n",
        "\n",
        "#### 2. Определяет столбцы свойств.\n",
        "\n",
        "Каждый `tf.feature_column` определяет имя признака, его тип и любую предобработку. Например, следующий фрагмент кода создает три столбца признаков содержащих целые числа или значения с плавающей точкой. Первые два столбца признаков просто идентифицируют имя признака и тип. Третий столбец признаков определяет лямбду - программу которая будет вызвана для масштабирования сырых данных:\n",
        "\n",
        "```\n",
        "# Определим три столбца с числовыми признаками.\n",
        "population = tf.feature_column.numeric_column('population')\n",
        "crime_rate = tf.feature_column.numeric_column('crime_rate')\n",
        "median_education = tf.feature_column.numeric_column(\n",
        "  'median_education',\n",
        "  normalizer_fn=lambda x: x - global_education_mean)\n",
        "```\n",
        "Для дополнительной информации см. [учебник по столбцам признаков](https://www.tensorflow.org/tutorials/keras/feature_columns).\n",
        "\n",
        "#### 3. Создание экземпляра готового оценщика.\n",
        "\n",
        "Например, вот так можно просто создать экземпляр оценщика `LinearClassifier`:\n",
        "\n",
        "```\n",
        "# Создадим экземпляр оценщика, передав столбцы признаков.\n",
        "estimator = tf.estimator.LinearClassifier(\n",
        "  feature_columns=[population, crime_rate, median_education])\n",
        "```\n",
        "Для дополнительной информации см. [учебник линейной классификации](https://www.tensorflow.org/tutorials/estimator/linear).\n",
        "\n",
        "#### 4. Вызов метода обучения, оценки или вывода.\n",
        "\n",
        "Например, все оценщики предоставляют метод `train` который обучает модель.\n",
        "\n",
        "```\n",
        "# `input_fn` это функция созданная на шаге 1\n",
        "estimator.train(input_fn=my_training_set, steps=2000)\n",
        "```\n",
        "Вы можете видеть пример этого ниже.\n",
        "\n",
        "### Преимущества готовых оценщиков\n",
        "\n",
        "Готовые оценщики включают в себя лучшие практики, предоставляя следующие преимущества:\n",
        "\n",
        "*   Лучшие практики для определения того, где должны выполняться различные части вычислительного графа, реализуя       стратегии на одной машине или на кластере.\n",
        "*   Лучшие практики для написания событий (сводок) и универсально полезные сводки.\n",
        "\n",
        "Если вы не используете готовые оценщики, вам нужно реализовать предыдущие функции самостоятельно."
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "oIaPjYgnZdn6"
      },
      "source": [
        "## Кастомные оценщики\n",
        "\n",
        "Сердцем каждого оценщика, будь он готовый или кастомный, является его *функция модели*, которая представляет собой метод построения графов для обучения, оценки и прогнозирования. Когда вы используете готовый оценщик, кто-то за вас уже реализовал функцию модели. Если вы пологаетесь на кастомнного оценщика, вам нужно написать функцию модели самостоятельно\n",
        "\n",
        "## Рекомендуемый процесс работы\n",
        "\n",
        "1. Предполагая, что существует готовый оценщик, используйте его для посторения своей первой модели и используйте его результаты для определения бейзлайна.\n",
        "2. Создайте и протестируйте весь конвейер, включая целостность и надежность ваших данных с этим готовым оценщиком.\n",
        "3. Если имеются другие подходящие готовые оценщики, проведите эксперименты какой из готовых оценщиков дает лучшие результаты.\n",
        "4. Возможно еще улучшить вашу модель созданием кастомного оценщика."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "kRr7DGZxFApM"
      },
      "outputs": [],
      "source": [
        "import tensorflow as tf"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "IqR2PQG4ZaZ0"
      },
      "outputs": [],
      "source": [
        "import tensorflow_datasets as tfds\n",
        "tfds.disable_progress_bar()"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "P7aPNnXUbN4j"
      },
      "source": [
        "## Создание оценщика из модели Keras\n",
        "\n",
        "Вы можете конвертировать существующие модели Keras models в оценщики с помощью `tf.keras.estimator.model_to_estimator`. Это позволяет вашей модели Keras\n",
        "получить сильные стороны оценщиков, такие как, например, распределенное обучение.\n",
        "\n",
        "Создайте экземпляр модели Keras MobileNet V2 и скомпилируйте модель с оптимизатором, потерями и метриками необходимыми для обучения:"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "XE6NMcuGeDOP"
      },
      "outputs": [],
      "source": [
        "keras_mobilenet_v2 = tf.keras.applications.MobileNetV2(\n",
        "    input_shape=(160, 160, 3), include_top=False)\n",
        "keras_mobilenet_v2.trainable = False\n",
        "\n",
        "estimator_model = tf.keras.Sequential([\n",
        "    keras_mobilenet_v2,\n",
        "    tf.keras.layers.Flatten(),\n",
        "    tf.keras.layers.Dense(1, activation='softmax')\n",
        "])\n",
        "\n",
        "# Компилируем модель\n",
        "estimator_model.compile(\n",
        "    optimizer='adam',\n",
        "    loss='binary_crossentropy',\n",
        "    metrics=['accuracy'])"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "A3hcxzcEfYfX"
      },
      "source": [
        "Создайте `Estimator` из скомпилированной модели Keras. Начальное состояние модели Keras сохранено в созданном `Estimator`:"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "UCSSifirfyHk"
      },
      "outputs": [],
      "source": [
        "est_mobilenet_v2 = tf.keras.estimator.model_to_estimator(keras_model=estimator_model)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "8jRNRVb_fzGT"
      },
      "source": [
        "Относитесь к полученному `Estimator` так же как к любому другому `Estimator`."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "Rv9xJk51e1fB"
      },
      "outputs": [],
      "source": [
        "IMG_SIZE = 160  # Размер всех изображений будет приведен к 160x160\n",
        "\n",
        "def preprocess(image, label):\n",
        "  image = tf.cast(image, tf.float32)\n",
        "  image = (image/127.5) - 1\n",
        "  image = tf.image.resize(image, (IMG_SIZE, IMG_SIZE))\n",
        "  return image, label"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "Fw8OjwujVBkc"
      },
      "outputs": [],
      "source": [
        "def train_input_fn(batch_size):\n",
        "  data = tfds.load('cats_vs_dogs', as_supervised=True)\n",
        "  train_data = data['train']\n",
        "  train_data = train_data.map(preprocess).shuffle(500).batch(batch_size)\n",
        "  return train_data"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "JMb0cuy0gbTi"
      },
      "source": [
        "Для обучения вызовите функцию обучения оценщика:"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "4JsvMp8Jge80"
      },
      "outputs": [],
      "source": [
        "est_mobilenet_v2.train(input_fn=lambda: train_input_fn(32), steps=500)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "jvr_rAzngY9v"
      },
      "source": [
        "Аналогично, для оценки вызовите функцию оценки оценщика:"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "kVNPqysQgYR2"
      },
      "outputs": [],
      "source": [
        "est_mobilenet_v2.evaluate(input_fn=lambda: train_input_fn(32), steps=10)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "5HeTOvCYbjZb"
      },
      "source": [
        "Дополнительную информацию можно получить в документации по `tf.keras.estimator.model_to_estimator`."
      ]
    }
  ],
  "metadata": {
    "accelerator": "GPU",
    "colab": {
      "collapsed_sections": [
        "Tce3stUlHN0L"
      ],
      "name": "estimator.ipynb",
      "toc_visible": true
    },
    "kernelspec": {
      "display_name": "Python 3",
      "name": "python3"
    }
  },
  "nbformat": 4,
  "nbformat_minor": 0
}
